#include "TextureData.h"
#include <GdiPlus.h>

using namespace Gdiplus;

namespace RayTracePro
{
	int CeilLog2(int val)
	{
		int rs = 0;
		while (val)
		{
			val>>=1;
			rs++;
		}
		return rs;
	}
	TextureData::TextureData(const GxLibBasic::String & fileName)
	{
		GdiplusStartupInput gdiplusStartupInput;
		ULONG_PTR gdiplusToken;
		GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
		FileName = fileName;
		{
			GxLibBasic::RefPtr<Bitmap> bmp;
			bmp = Bitmap::FromFile(fileName.GetStrPtr());
			Width = bmp->GetWidth();
			Height = bmp->GetHeight();
			if (Width == 0 || Height == 0)
				return;
			Levels.SetSize(CeilLog2(max(Width, Height)));
			Levels[0].Pixels.SetSize(Width * Height);
			Levels[0].Height = Height;
			Levels[0].Width = Width;
			BitmapData data;
			bmp->LockBits(&Rect(0,0, Width, Height), ImageLockModeRead, PixelFormat32bppARGB, &data);
			for (int i = 0; i<(int)data.Height; i++)
			{
				int * pixels = (int*)((char*)data.Scan0 + data.Stride*i);
				for (int j = 0; j<(int)data.Width; j++)
				{
					Levels[0].Pixels[i*data.Width + j].Value = pixels[j];
					unsigned char tmp = Levels[0].Pixels[i*data.Width + j].B;
					Levels[0].Pixels[i*data.Width + j].B = Levels[0].Pixels[i*data.Width + j].R;
					Levels[0].Pixels[i*data.Width + j].R = tmp;
				}
			}
			bmp->UnlockBits(&data);
		}
		GdiplusShutdown(gdiplusToken);

		int level = 0;
		int lwidth = Width, lheight = Height;
		do
		{
			int oldWidth = lwidth;
			int oldHeight = lheight;
			int oldLevel = level;
			level++;
			lwidth >>= 1;
			lheight >>= 1;
			if (lwidth == 0) lwidth = 1;
			if (lheight == 0) lheight = 1;
			Levels[level].Width = lwidth;
			Levels[level].Height = lheight;
			Levels[level].Pixels.SetSize(lwidth * lheight);
			for (int i = 0; i<lheight; i++)
			{
				int i1, i2;
				if (lheight < oldHeight)
				{
					i1 = i*2;
					i2 = i1 + 1;
				}
				else
				{

					i1 = i2 = i;
				}
				for (int j = 0; j<lwidth; j++)
				{
					int j1, j2;
					if (lwidth < oldWidth)
					{
						j1 = j*2;
						j2 = j1 + 1;
					}
					else
					{
						j1 = j2 = j;
					}
					Color c1,c2,c3,c4;
					c1 = Levels[oldLevel].Pixels[i1*oldWidth + j1];
					c2 = Levels[oldLevel].Pixels[i1*oldWidth + j2];
					c3 = Levels[oldLevel].Pixels[i2*oldWidth + j1];
					c4 = Levels[oldLevel].Pixels[i2*oldWidth + j2];
					Color c;
					c.R = (c1.R+c2.R+c3.R+c4.R)>>2;
					c.G = (c1.G+c2.G+c3.G+c4.G)>>2;
					c.B = (c1.B+c2.B+c3.B+c4.B)>>2;
					c.A = (c1.A+c2.A+c3.A+c4.A)>>2;
					Levels[level].Pixels[i*lwidth + j] = c;
				}
			}
		}
		while (lwidth != 1 || lheight != 1);
	}
}